//============================================================================
// Name        : cpptest.cpp
// Author      : Zyan
// Version     :
// Copyright   : Your copyright notice
// Description : Hello World in C++, Ansi-style
//============================================================================

#include <iostream>
#include <vector>
using namespace std;

//#define CRTP
//#define SINGLETON
//#define CALCULATION 
//#define SQRT 
//#define META_PROGRAM
//#define PLACEHOLDER1
#define PLACEHOLDER2
//#define CROSSCOMPILE

template<bool flag, typename X, typename Y>
class if_else
{
   public:
      typedef X type;
};
template<typename X, typename Y>
class if_else<false, X, Y>
{
   public:
      typedef Y type;
};
template<unsigned int VALUE>
class uint_type
{
   public:
      static const unsigned int value = VALUE; 
};



	// Static is no weaker than Dynamic
#ifdef CRTP
	template <typename T>
	class number
	{
	public:
		bool operator >(T const &rhs) const
		{
			T const &self = static_cast<T const&>(*this);
			return rhs < self;
		}
	};
	
	template <typename T>
	class signed_number: public number<T>
	{
	public:
		friend T abs(T const& x)
		{
			return x > 0 ? x : -x;
		}
	};
	
	class Float: public signed_number<Float>
	{
	public:
		Float(float x): m_value(x) {}
		Float operator-() const
		{
			return Float(-m_value);
		}
		bool operator<(Float const &rhs) const
		{
			return m_value < rhs.m_value;
		}
	private:
		float m_value;
	};
	int main()
	{
		cout<<"3.7 > 4.3: "<<(Float(3.7)>Float(4.3))<<endl;
		cout<<"abs(-4.3) > 3.7: "<<(abs(Float(-4.3))>Float(3.7))<<endl; 
	}
#endif
#ifdef SINGLETON
	template <typename T> struct CreateNew {
	  static T* Create() { return new T; }
	};

	template <typename T> struct CreateStatic {
	  static T* Create() {
	    static T _instance;
	    return &_instance;
	  }
	};

	// This Singleton class accepts different creation policies.
	template <typename T, template<typename X> class CreationPolicy=CreateStatic>
	class Singleton {
	public:
	  static T& Instance() {
	    if (!m_pInstance)
	      m_pInstance=CreationPolicy<T>::Create();
	    return *m_pInstance;
	}

	private:
	  Singleton();          // ctor hidden
	  ~Singleton();          // dtor hidden
	  Singleton(Singleton const&);    // copy ctor hidden
	  Singleton& operator=(Singleton const&);  // assign op hidden

	  static T* m_pInstance;
	};
	template <typename T, template<typename X> class C>
	T* Singleton<T,C>::m_pInstance = NULL;
	
	class Tracer
	{
	public:
		Tracer() { cout << "construct: %x"<<this<<endl; }
		~Tracer() { cout << "destruct: %x"<<this<<endl; }
		void show_me() { cout << "this is: %x"<<this<<endl; }
	};
	typedef Singleton<Tracer, CreateNew> TracerSingletonNew;
	typedef Singleton<Tracer> TracerSingletonStatic;
	int main()
	{
		TracerSingletonNew::Instance().show_me();
		TracerSingletonNew::Instance().show_me();
		TracerSingletonStatic::Instance().show_me();
		return 1;
	}
#endif
#ifdef CALCULATION
	template<unsigned int N>
	class calculate_N
	{
	public:
		static const unsigned int value = N * calculate_N<N-1>::value;
	};
	template<>
	class calculate_N<1>
	{
	public:
		static const unsigned int value = 1; 
	};
	
	template<unsigned long long N>
	class binary
	{
	public:
		static const unsigned long long value = 
			binary<N%10>::value + (binary<N/10>::value << 1);
	};
	template<>
	class binary<1>
	{
	public:
		static const unsigned long long value = 1;
	};
	template<>
	class binary<0>
	{
	public:
		static const unsigned long long value = 0;
	};
	int main()
	{
		cout<<"6! = "<<calculate_N<6>::value<<endl;
		cout<<"0b11110010 = 0x"<<hex<<binary<10110010>::value<<endl;
	}
#endif
#ifdef SQRT
template<unsigned int N, unsigned int MIN = 1, unsigned int MAX = N>
class sqrt
{
   public:
      static const unsigned int mid = (MIN + MAX + 1) / 2;
      static const unsigned int value
	  = N < mid * mid ? sqrt<N, MIN, mid - 1>::value 
	  : sqrt<N, mid, MAX>::value;
};
template<unsigned N, unsigned int M>
class sqrt<N,M,M>
{
   public:
      static const unsigned int value = M;
};

template<unsigned N, unsigned int MIN = 1, unsigned int MAX = N>
class quick_sqrt
{
   public:
      static const unsigned int mid = (MIN + MAX + 1) / 2;
      static const unsigned int value = if_else< MIN == MAX, 
                   uint_type<MAX>, 
                   typename if_else< N<mid*mid, 
                      quick_sqrt<N, MIN, mid - 1>, 
                      quick_sqrt<N, mid, MAX> >::type >
					  ::type::value;
};

int main()
{
   cout<<"sqrt(9) = "<<sqrt<9>::value<<endl;
   //cout<<"sqrt(2209) = "<<sqrt<2209>::value<<endl;
   cout<<"quick_sqrt(3200521) = "<<quick_sqrt<3200521>::value<<endl;
   return 1;
}
#endif
#ifdef META_PROGRAM
template<typename X, typename Y>
class is_same
{
   public:
      static const bool value = false;
};

template<typename X>
class is_same<X,X>
{
   public:
      static const bool value = true;
};

template<typename X>
class is_function
{
   private:
      typedef char One;
      typedef struct { char a[2]; } Two;
      template<typename U> static One test(...);
      template<typename U> static Two test(U (*)[1]);
   public:
      static const bool value = sizeof(test<X>(0)) == 1;
};

template<>
class is_function<void const>
{
   public:
      static const bool value = false;
};
template<>
class is_function<void>
{
   public:
      static const bool value = false;
};
template<typename T>
class is_function<T&>
{
   public:
      static const bool value = false;
};


class add_pointer
{
   public:
      template<typename T>
      struct apply
      {
         typedef T* type;
      };
};
class add_reference
{
   public:
      template<typename T>
      struct apply
      {
         typedef T& type;
      };
};
template<typename MFA, typename MFB, typename T>
class combo
{
   public:
      typedef typename MFA::template apply<typename MFB::template apply<T>::type>::type type;
};


int main()
{
   cout<<"apply add_reference and add_pointer to int is equal to int*&: "<<
      is_same<combo<add_reference, add_pointer, int>::type, int*&>::value<<endl;
   typedef int func();
   cout<<"is func() a function type: "<<is_function<func>::value<<endl;
   cout<<"is add_reference a function: "<<is_function<add_reference>::value<<endl;
   cout<<"is int a function: "<<is_function<int>::value<<endl;
   return 0;
}
#endif
#ifdef PLACEHOLDER1

 
template<typename X, typename Y>
class trait_add_type
{
   public:
	  typedef char One;
	  typedef struct { char a[2]; } Two;
	  One test(X);
	  Two test(Y);
      typedef typename if_else<sizeof(X()+Y()) == 1, X, Y>::type type;
};

class arg_1
{

   public:
      template<typename X, typename Y>
         X &operator()(X &a, Y &b) const
         {
            return a;
         }
} _1;
class arg_2
{
   public:
      template<typename X, typename Y>
         Y &operator()(X &a, Y &b) const
         {
            return b;
         }
} _2;

template<typename T>
class arg_const
{
   private:
      T m_val;
   public:
      arg_const(T val): m_val(val) { }
      template<typename X, typename Y>
         T operator()(X &a, Y &b) const
         {
            return m_val;
         }
};

template<typename T>
class trait_arg
{
   public:
      typedef arg_const<T> type;
};
template<>
class trait_arg<arg_1>
{
   public:
      typedef arg_1 type;
};
template<>
class trait_arg<arg_2>
{
   public:
      typedef arg_2 type;
};

template<typename ARG1, typename ARG2>
class add_arg
{
   private:
      ARG1 m_op1;
      ARG2 m_op2;
   public:
      add_arg(ARG1 op1, ARG2 op2): m_op1(op1), m_op2(op2) { }
      template<typename X, typename Y>
         typename trait_add_type<X, Y>::type
         operator()(X &a, Y &b)
         {
            return m_op1(a,b) + m_op2(a, b);
         }
};
template<typename ARG1, typename ARG2>
class trait_arg<add_arg<ARG1, ARG2> >
{
   public:
      typedef add_arg<ARG1, ARG2> type;
};

template<typename X, typename Y>
   add_arg<typename trait_arg<X>::type, typename trait_arg<Y>::type> 
operator +(X x, Y y)
{
   return add_arg<typename trait_arg<X>::type, typename trait_arg<Y>::type>
      (typename trait_arg<X>::type(x), typename trait_arg<Y>::type(y));
};


int main()
{
   int u[6] = { 0, 1, 2, 3, 4, 5};
   vector<float> v; v.push_back(5.5); v.push_back(4.4); v.push_back(3.3); v.push_back(2.2); v.push_back(1.1); v.push_back(0.0);
   double w[6];
   transform(u, u+6, v.begin(), w, 10.1 + _1 + _2 + 1);
   cout<<w[0]<<" "<<w[1]<<" "<<w[2]<<" "<<w[3]<<" "<<w[4]<<" "<<w[5]<<endl;
   return 0;
}
#endif
#ifdef PLACEHOLDER2
template <int N> struct arg; // forward declarations
struct void_;

template <>
struct arg<1>
{
   template <
      class A1, class A2 = void_>
      struct apply
      {
         typedef A1 type; // return the first argument
      };
};
typedef arg<1> _1;

template <>
struct arg<2>
{
   template <class A1, class A2>
      struct apply
      {
         typedef A2 type; // return the second argument
      };
};
typedef arg<2> _2;

template<typename Func>
struct lambda
{
   typedef Func type;
};

template<int N, template <typename> class Func>
struct lambda<Func<arg<N> > >
{
   typedef struct
   {
      template <typename T>
         struct apply
         {
            typedef typename Func<typename arg<N>::template apply<T>::type >::type type;
         };
   } type;
};

template <typename F, typename X>
struct twice
: lambda<F>::type::template apply<
   typename lambda<F>::type::template apply<X>::type>
{};

struct add_struct_f
{
   template<typename T>
      struct apply
      {
         typedef struct { T a; char c; } type;
      };
};
template<typename T>
struct add_struct
{
   typedef struct { T a; char c; } type;
};

struct 
{
   struct
   {
      int a;
      char c;
   } a;
   char c;
} nested;

typedef twice<add_struct_f, int>::type constructed;
int main()
{
   cout<<"Same size?: "<<(sizeof(twice<add_struct_f, int>::type)==sizeof(nested))<<endl;
   cout<<"Same size?: "<<(sizeof(twice<add_struct<_1>, int>::type)==sizeof(twice<add_struct_f, int>::type));
   return 0;
}

#endif
#ifdef CROSSCOMPILE
struct void_;
template <typename T, typename TAIL>
class type_seq
{
   public:
      struct self
      {
         typedef T type;
      };
      typedef TAIL tail;
      template<int bytes>
         struct apply
         {
            typedef typename if_else<bytes==sizeof(typename self::type), 
                    self, 
                    typename tail::template apply<bytes> >::type::type type;
         };
};
template<bool sig, unsigned int bytes>
class type_selector
{
   private:
      typedef 
         type_seq<char, 
         type_seq<short, 
         type_seq<int, 
         type_seq<long, 
         type_seq<long long, 
         type_seq<void_,  void_> > > > > > stypes;

      typedef 
         type_seq<unsigned char, 
         type_seq<unsigned short, 
         type_seq<unsigned int, 
         type_seq<unsigned long, 
         type_seq<unsigned long long, 
         type_seq<void_,  void_> > > > > > utypes;
   public:
      typedef typename if_else<sig, stypes, utypes>::type types;
      typedef typename types::template apply<bytes>::type type;
};


typedef type_selector<true, 1>::type int8;
typedef type_selector<false, 8>::type uint64;
typedef type_selector<true, 7>::type int56;


int main()
{
   int8 i8 = 'a';
   uint64 u64 = uint64(-1);
   cout<<"sizeof(i8): "<<sizeof(i8)<<endl;
   cout<<"sizeof(u64): "<<sizeof(u64)<<endl;
   cout<<"i8 u64: "<<i8<<" "<<u64<<endl;
   return 0;
}
#endif

